<?php

namespace extend;

use app\Manage;

class Table
{
    /**
     * 获取表字段信息
     *
     * @param $table
     *
     * @return array
     */
    static function getFields($table)
    {
        global $qe_db_config;

        $db = $qe_db_config['db'];

        $sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name ='{$table}' AND table_schema = '{$db}'";


        $table_info = db()->query($sql);

        $fields = [];

        foreach ($table_info as $key => $field) {

            $fields[$field['COLUMN_NAME']] = [
                'title' => $field['COLUMN_COMMENT'] ? strtoupper($field['COLUMN_COMMENT']) : strtoupper($field['COLUMN_NAME']),
                'name' => $field['COLUMN_NAME'],
                'type' => $field['DATA_TYPE'],
                'option' => $field['DATA_TYPE'] == 'enum' ? explode(',', str_replace(['enum(', ')', '\''], '', $field['COLUMN_TYPE'])) : ''
            ];
        }

        return $fields;

    }

    static function getModes($table)
    {   
        $modes = db()->where('table_name', $table)->get('qe_config', null, 'DISTINCT mode');
        //打印sql
        //print_r(db()->getLastQuery());
        return array_column($modes, 'mode');
    }

    /**
     * 获取表字段
     * @auth false
     * @param $table
     * @param array $include
     * @return array
     */
    static function getFieldMap($table, array $include = [])
    {
        $fields = self::getFields($table);
        $result = [];
        if ($fields) {
            foreach ($fields as $row) {
                if ($include && !in_array($row['name'], $include)) {
                    continue;
                }
                $result[$row['name']] = $row['title'];
            }
        }
        return $result;
    }


    /**
     * getDbTableName
     * @param null $_table
     *
     * @return array|mixed
     */
    static function getName($_table = null)
    {

        global $qe_db_config;
        $db = $qe_db_config['db'];

        $sql = "SELECT TABLE_NAME,TABLE_COMMENT FROM information_schema.TABLES WHERE table_schema='{$db}'";
        $res = db()->query($sql);

        if ($res) {
            $arr = [];
            foreach ($res as $table) {
                $arr[$table['TABLE_NAME']] = $table['TABLE_COMMENT'] ? str_replace(['表'], '', $table['TABLE_COMMENT']) : strtoupper($table['TABLE_NAME']);
            }
            $res = $arr;
        }

        return $_table ? $res[$_table] : $res;
    }


    static function getConfig($table, $type = 'user',$act='edit')
    {

        $config = db()->where('table_name', $table)->where('mode', $type)->getOne(CONFIG_TABLE);

        if (!$config) {
            return false;
        }

        foreach (Manage::$list_fields as $f) {
            if ($config[$f]) {
                $config[$f] = explode(',', $config[$f]);
            }
        }
        $fields = self::getFields($table);

        $all_fields = array_keys($fields);

        if ($config['pk']) {

            if (!isset($config['edit_fields']) || !$config['edit_fields']) {
                $config['edit_fields'] = [];
            }

//            $config['edit_fields'][] = $config['pk'];
            array_unshift($config['edit_fields'],$config['pk']);
        }

        $field_options = [];

        if ($config['field_options']) {
            $field_options = json_decode($config['field_options'], true);
        }

        $edit_fields = $config['edit_fields'] ?: $all_fields;


        $list_fields = $config['list_fields'] ?: $all_fields;

        $default_value_fields = $condition_fields = [];

        if ($field_options) {
            foreach ($field_options as $field_key => $field) {


                if (isset($field['default_value']) && $field['default_value'] && in_array($field_key, $all_fields)) {
                    $default_value_fields[$field_key] = $field['default_value'];
                }

                if (isset($field['condition']) && $field['condition'] && in_array($field_key, $all_fields)) {
                    $condition_fields[$field_key] = $field['condition'];
                }

                $filter_fields=$act=='edit'?$edit_fields:$list_fields;

                if (!in_array($field_key, $filter_fields) || !in_array($field_key, $all_fields)) {
                    unset($field_options[$field_key]);
                    continue;
                }


                if (in_array($field['type'], [' ', '请选择'])) $field_options[$field_key]['type'] = 'text';

                if (in_array($field['option_callback'], [' ', '请选择'])) $field_options[$field_key]['option_callback'] = '';

                if (method_exists(FieldSet::class, $field['option_callback'])) {
                    $field_options[$field_key]['option_value'] = call_user_func_array([FieldSet::class, $field['option_callback']], [$field]);
                }
            }
        }

        $config['field_options'] = $field_options;

        $arr = [];

        $struct = [];

        foreach ($fields as $field) {
            //in_array($field['name'],$edit_fields) &&
            if (in_array($field['name'], $all_fields)) {
                $arr[$field['name']] = $field['title'];

                $struct[$field['name']] = '';
            }
        }
        $config['list_fields'] = $list_fields;
        $config['edit_fields'] = $edit_fields;
        $config['field_titles'] = $arr;
        $config['default_value_fields'] = $default_value_fields;
        $config['condition_fields'] = $condition_fields;
        $config['struct'] = $struct;

        return $config;

    }


    static function getAreas($position)
    {

        $levels = [];

        $levels = self::getLeveArea($position, $levels);

        $self = current($levels);

        $sons_arr = $parents_arr = [];

        if ($self) {
            $sons = db()->where('pcode', $self['code'])->get(AREA_DATA_TABLE);

            if ($sons) {
                foreach ($sons as $k => $item) {
                    $sons_arr[$item['code']] = $item;
                }
            }

            $parents = db()->where('pcode', $self['pcode'])->get(AREA_DATA_TABLE);

            if ($parents) {
                foreach ($parents as $k => $item) {
                    $parents_arr[$item['code']] = $item;
                }
            }
        }
        return ['self' => $self, 'parents' => $parents_arr, 'sons' => $sons_arr, 'level' => $levels];
    }

    static function getLeveArea($position, &$data = [])
    {
        $self = db()->where('code', $position)->getOne(AREA_DATA_TABLE);

        if ($self) {

            $data[$self['level']] = ['code' => $self['code'], 'name' => $self['name'], 'level' => $self['level'], 'pcode' => $self['pcode']];

            if ($self['pcode']) {
                return self::getLeveArea($self['pcode'], $data);
            }
        }
        return $data;
    }


    /**
     * 递归获取子级地区
     * @auth false
     * @param $pos
     * @param $data
     * @return array|mixed
     */
    static function getSonRelations($pos, $data)
    {

        $pos = is_array($pos) ? $pos : ($pos ? [$pos] : []);
        $son_pos = [];

        if ($pos) {
            $in = '(\'' . implode('\',\'', $pos) . '\')';
            $son_pos = db()->where("pcode IN {$in}")->get(AREA_DATA_TABLE, null, ['GROUP_CONCAT(code) as code']);
            $son_pos = $son_pos ? array_filter(explode(',', $son_pos[0]['code'])) : [];


        }

        $result = array_unique(array_merge($data, $son_pos));

        $son_pos && $result = self::getSonRelations($son_pos, $result);

        return $result;

    }


    static function parseConditionValue($condition_str,$field_key,$data=[],$return=false)
    {
        $editable=true;
        $conditions = array_filter(preg_split("/\r\n/", $condition_str));
        $result=[];
        if ($conditions) {
            // =  callback|user_id
            foreach ($conditions as $v_callback) {
                $tmp = array_values(array_filter(preg_split("/[ \|]/", $v_callback)));

                if (!isset($tmp[1])) continue;

                $where = $tmp[0];

                $value = $tmp[1];

                switch ($tmp[1]) {
                    case 'callback':
                        if (isset($tmp[2])) {
                            if (method_exists(DefaultValue::class, $tmp[2])) {
                                $value = call_user_func_array([DefaultValue::class, $tmp[2]], []);
                            } elseif (is_callable($tmp[2])) {
                                $value = call_user_func($tmp[2]);
                            }
                        }
                        break;
                    case 'params':
                        $arr=explode(':',$tmp[2]);

                        if(!isset($data[$arr[0]]) || (isset($data[$arr[0]][$arr[1]]) && !is_string($data[$arr[0]][$arr[1]]))){
                            //参数设置错误
                            throw new \Exception($field_key.'条件参数错误');
                        }

                        $value = $data[$arr[0]][$arr[1]] ?? (is_string($data[$arr[0]]) ? $data[$arr[0]] : '');

                        break;
                }

                if($return){
                    $result[$field_key][]=[$where,$value];
                    continue;
                }


                switch ($where) {
                    case '=':
                        if ($data[$field_key] != $value) $editable = false;
                        break;
                    case '>':
                        if ($data[$field_key] < $value) $editable = false;
                        break;
                    case '<':
                        if ($data[$field_key] > $value) $editable = false;
                        break;
                    case '<>':
                    case '!=':
                        if ($data[$field_key] == $value) $editable = false;
                        break;
                }

                if(!$editable){
                    break;
                }

            }
        }

        return $return ? $result :$editable;
    }
}